package com.itheima.app.manager;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.itheima.autoconfig.aip.AipFaceTemplate;
import com.itheima.autoconfig.im.HuanXinTemplate;
import com.itheima.autoconfig.oss.OssTemplate;
import com.itheima.autoconfig.sms.SmsTemplate;
import com.itheima.domain.db.Log;
import com.itheima.domain.db.User;
import com.itheima.domain.db.UserInfo;
import com.itheima.domain.vo.ErrorResult;
import com.itheima.domain.vo.UserInfoVo;
import com.itheima.service.db.UserInfoService;
import com.itheima.service.db.UserService;
import com.itheima.util.ConstantUtil;
import com.itheima.util.JwtUtil;
import org.apache.dubbo.config.annotation.Reference;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.time.Duration;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

@Service //spring
public class UserManager {

    @Reference //dubbo
    UserService userService;

    @Autowired
    SmsTemplate smsTemplate;

    @Autowired
    StringRedisTemplate redisTemplate;

    @Reference
    UserInfoService userInfoService;

    @Autowired
    AipFaceTemplate aipFaceTemplate;

    @Autowired
    OssTemplate ossTemplate;

    @Autowired
    HuanXinTemplate huanXinTemplate;

    @Autowired
    RocketMQTemplate rocketMQTemplate;

    public ResponseEntity save(User user){
        Long userId = userService.save(user);
        //若操作成功 ResponseEntity.ok([返回数据])
        //若操作失败 ResponseEntity.status(500).body(错误信息)
        return ResponseEntity.ok(userId);
    }

    public ResponseEntity findByPhone(String phone){
        User user = userService.findByPhone(phone);
        return ResponseEntity.ok(user);
    }

    public ResponseEntity sendCode(String phone) {
        //1.生成随机验证码 (123456)
        //TODO 上线后开启随机验证码
        //String code = RandomUtil.randomNumbers(6);
        String code = "123456";

        //2.调用模版对象发送验证码
        //TODO 上线后开启发送验证码
        //smsTemplate.sendSms(phone,code);

        //3.调用redis模版对象,将验证码放入redis(时效)
        redisTemplate.opsForValue().set(ConstantUtil.SMS_CODE+phone,code, Duration.ofMinutes(5));
        return ResponseEntity.ok(null);
    }

    public ResponseEntity regAndLogin(String phone, String requestCode) {
        //1.校验验证码是否正确
        String redisCode = redisTemplate.opsForValue().get(ConstantUtil.SMS_CODE + phone);

        //2.若错误,返回错误信息
        if (!StrUtil.equals(redisCode,requestCode)) {
            return ResponseEntity.status(500).body(ErrorResult.loginError());
        }

        //3.若正确,删除验证码,调用service.findByPhone(),返回user
        redisTemplate.delete(ConstantUtil.SMS_CODE + phone);

        User user = userService.findByPhone(phone);

        //4.判断user是否为null
        boolean isNew;
        //4.1 若为null,isNew=true,保存新用户
        if (user == null) {
            isNew = true;

            user = new User();
            //给用户设置电话号
            user.setPhone(phone);

            //保存用户
            Long userId = userService.save(user);

            //把用户id设置到用户
            user.setId(userId);


            // TODO 向环信服务器注册用户
            huanXinTemplate.register(userId);
        }else{
            //4.2  若不为null,isNew=false
            isNew = false;
        }

        //5.生成token,
        HashMap<Object, Object> claims = new HashMap<>();
        claims.put("id",user.getId());
        claims.put("phone",user.getPhone());

        String token = JwtUtil.createToken(claims);

        //6.将token和isNew封装到map中返回即可
        Map<String,Object> map = new HashMap<>();
        map.put("token",token);
        map.put("isNew",isNew);


        //7.给用户的登陆设置一个时效 例如:5天 就需要把token保存到redis中
        // 还可以将用户信息作为value放入redis中(可选)
        redisTemplate.opsForValue().set(ConstantUtil.USER_TOKEN+token, JSON.toJSONString(user),Duration.ofDays(5));


        //8.组装日志对象,发送到mq中
        Log log = new Log();

        log.setUserId(user.getId());
        log.setLogTime(DateUtil.formatDate(new Date()));

        //若是新用户还没有上报地址,若是老用户就可以去userLocation表中获取地址
        log.setPlace("北京顺义黑马程序员");
        log.setEquipment("华为");
        log.setType(isNew?"0102":"0101");

        //9.发送到mq中
        rocketMQTemplate.convertAndSend("tanhua-log",log);

        return ResponseEntity.ok(map);
    }

    public ResponseEntity saveUserInfo(UserInfo userInfo, String token) {
        //1.判断令牌是否为空,为空返回401
        if (StrUtil.isBlank(token)) {
            return ResponseEntity.status(401).body(null);
        }

        //2.从redis中查询指定token,为空返回401
        String userJson = redisTemplate.opsForValue().get(ConstantUtil.USER_TOKEN + token);
        if (StrUtil.isBlank(userJson)) {
            return  ResponseEntity.status(401).body(null);
        }

        //3.获取user
        User user = JSON.parseObject(userJson, User.class);

        //4.给token续期
        redisTemplate.opsForValue().set(ConstantUtil.USER_TOKEN+token,userJson,Duration.ofDays(5));

        //5.给UserInfo设置id
        userInfo.setId(user.getId());

        //6.调用service完成保存操作
        userInfoService.save(userInfo);
        return ResponseEntity.ok(null);
    }


    public ResponseEntity saveUserInfoHead(MultipartFile headPhoto, String token) throws IOException {
        //1.判断令牌是否为空,为空返回401
        if (StrUtil.isBlank(token)) {
            return ResponseEntity.status(401).body(null);
        }

        //2.从redis中查询指定token,为空返回401
        String userJson = redisTemplate.opsForValue().get(ConstantUtil.USER_TOKEN + token);
        if (StrUtil.isBlank(userJson)) {
            return  ResponseEntity.status(401).body(null);
        }

        //3.获取user
        User user = JSON.parseObject(userJson, User.class);

        //4.给token续期
        redisTemplate.opsForValue().set(ConstantUtil.USER_TOKEN+token,userJson,Duration.ofDays(5));

        //5.人脸检测,若没有通过,返回提示
        boolean detect = aipFaceTemplate.detect(headPhoto.getBytes());
        if (!detect) {
            //检测不通过
            return ResponseEntity.status(500).body(ErrorResult.faceError());
        }

        //6.把头像存入oss,返回url
        String url = ossTemplate.upload(headPhoto.getOriginalFilename(), headPhoto.getInputStream());

        //7.创建userInfo,设置id和设置头像
        UserInfo userInfo = new UserInfo();
        userInfo.setId(user.getId());

        userInfo.setAvatar(url);//头像
        userInfo.setCoverPic(url);//封面

        //8.调用service完成更新
        userInfoService.update(userInfo);

        return ResponseEntity.ok(null);
    }

    public ResponseEntity findUserInfoById(Long id) {
        //1.根据id,调用service查询UserInfo
        UserInfo userInfo = userInfoService.findById(id);

        //2.创建UserInfoVo(封装返回结果)
        UserInfoVo userInfoVo = new UserInfoVo();

        //3.将UserInfo中的信息拷贝到UserInfoVo
        BeanUtil.copyProperties(userInfo,userInfoVo);

        //4.返回vo
        return ResponseEntity.ok(userInfoVo);
    }

    public ResponseEntity updateUserInfo(UserInfo userInfo) {
        userInfoService.update(userInfo);
        return ResponseEntity.ok(null);
    }
}
